package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.model.wemedia.pojos.WmUser;
import com.heima.utils.thread.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmMaterialMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmNewsMaterialMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmNewsService;
import lombok.extern.slf4j.Slf4j;


import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.cert.ocsp.Req;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;

    @Autowired
    private WmMaterialMapper wmMaterialMapper;

    @Override
    public ResponseResult findAll(WmNewsPageReqDto dto) {
        //1:检查dto参数
        if (dto == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2:检查分页参数
        dto.checkParam();
        //3:从threadLocal中获取当前登录人的信息
        WmUser user = WmThreadLocalUtil.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //4:构造分页器
        Page<WmNews> page = new Page<>(dto.getPage(), dto.getSize());
        //5: 构造查询条件 状态精确查询
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        if (dto.getStatus() != null) {
            queryWrapper.eq("status", dto.getStatus());
        }
        //频道精确查询
        if (dto.getChannelId() != null) {
            queryWrapper.eq("channel_id", dto.getChannelId());
        }
        //时间范围查询
        if (dto.getBeginPubdate() != null) {
            queryWrapper.between("created_time", dto.getBeginPubdate(), dto.getEndPubdate());
        }
        //关键字模糊查询
        if (!StringUtils.isEmpty(dto.getKeyword())) {
            queryWrapper.like("title", dto.getKeyword());
        }
        //查询当前登录用户的文章
        queryWrapper.eq("user_id", user.getId());
        //发布时间倒序查询
        queryWrapper.orderByDesc("created_time");
        //6:封装返回结果
        page = page(page, queryWrapper);
        ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), (int) page.getTotal());
        responseResult.setData(page.getRecords());
        //responseResult.setHost("");
        return responseResult;
    }


    @Override
    public ResponseResult submitNews(WmNewsDto dto) {
        //判断参数
        if (dto.getContent() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //文章布局 0无图 1单图 3多图
        if (dto.getType() == -1) {
            dto.setType(null);
        }
        WmNews wmNews = new WmNews();
        BeanUtils.copyProperties(dto, wmNews);
        //封装images到wmnews实体中
        List<String> images = dto.getImages();
        if (images != null && images.size() > 0) {
            String imgStr = StringUtils.join(images, ",");
            wmNews.setImages(imgStr);
        }
        //执行保存或者修改
        saveorUpdateNews(wmNews);
        //若果是草稿则返回
        if (dto.getStatus() == 0) {
            return ResponseResult.okResult(null);
        }
        //3.2 关联文章内容图片与素材的关系
        //3.3 关联文章封面图片与素材的关系
        List imageList = chouquImageList(wmNews);
        //4.如果包含了id，则为修改请求
        contentImageToNews(wmNews, imageList, (short) 0);
        //4.1 删除该文章与素材的所有关系
        //4.2 执行修改操作
        //4.3 关联文章内容图片与素材的关系
        //4.4 关联文章封面图片与素材的关系
        fengmianImageToNews(wmNews, dto, imageList, (short) 1);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }


    /**
     * 抽取的第四个方法，关联封面图片与文章的关系，操作中间表
     * 如果封面类型是自动的话，从文章内容中图片进行操作
     * 如果文章内容图片个数大于1，小于3的话，则认为单图
     * 如果文章内容图片个数大于等于3的话，则认为多图
     * 如果文章内容图片个数，则认为是无图
     *
     * @param wmNews
     * @param type
     */
    private void fengmianImageToNews(WmNews wmNews, WmNewsDto dto, List imageList, short type) {
        //1.获取封面图片
        List<String> images = dto.getImages();

        //自动
        if (dto.getType() == null) {
            if (imageList.size() >= 1 && imageList.size() < 3) {
                //取出第一张图片作为封面
                images = (List<String>) imageList.stream().limit(1).collect(Collectors.toList());
                //单图设置类型
                wmNews.setType((short) 1);
            } else if (imageList.size() >= 3) {
                images = (List<String>) imageList.stream().limit(3).collect(Collectors.toList());
                //多图设置类型
                wmNews.setType((short) 3);
            } else {
                wmNews.setType((short) 0);
            }

            wmNews.setImages(StringUtils.join(images, ","));
            updateById(wmNews);
        }
        //否则，直接插入到中间表中
        saveNewsMaterial(wmNews, type, images);
    }

    /**
     * 第五个抽取方法
     *
     * @param wmNews
     * @param type
     * @param images
     */
    private void saveNewsMaterial(WmNews wmNews, short type, List<String> images) {
        //1.判断imageList是否有值
        if (images != null && images.size() > 0) {
            //根据地址集合去查询素材表
            List<WmMaterial> wmMaterials = wmMaterialMapper.selectList(Wrappers.<WmMaterial>lambdaQuery().in(WmMaterial::getUrl, images));
            //2.要从素材集合中只抽取出相对应的id集合
            List<Integer> materialIds = wmMaterials.stream().map(WmMaterial::getId).collect(Collectors.toList());

            /**
             * 参数1表示素材id集合
             * 参数2表示文章id
             * 参数3表示引用类型
             */
            wmNewsMaterialMapper.saveRelations(materialIds, wmNews.getId(), type);
        }
    }

    /**
     * 第三个抽取方法，关联内容中的图片与文章的关系，操作中间表
     *
     * @param wmNews    文章实体
     * @param imageList 内容中抽取的图片集合,图片地址集合
     * @param type      引用类型，0表示内容引用 1表示封面引用
     */
    private void contentImageToNews(WmNews wmNews, List imageList, Short type) {

        saveNewsMaterial(wmNews, type, imageList);
    }

    /**
     * 第二个抽取方法，为了从文章内容中抽取图片集合
     *
     * @param wmNews
     * @return
     */
    private List chouquImageList(WmNews wmNews) {

        List imageList = new ArrayList();

        //1.获取内容
        String content = wmNews.getContent();
        //2.转化list类型
        List<Map> list = JSON.parseArray(content, Map.class);
        for (Map map : list) {
            if (map.get("type").equals("image")) {
                String value = (String) map.get("value");
                imageList.add(value);
            }
        }
        return imageList;
    }

    /**
     * 第一个抽取方法，修改或者保存
     *
     * @param wmNews
     */
    //1.前端提交发布或保存为草稿
    //2.后台判断请求中是否包含了文章id
    //3.如果不包含id,则为新增
    //3.1 执行新增文章的操作
    private void saveorUpdateNews(WmNews wmNews) {
        //补全属性
        wmNews.setCreatedTime(new Date());
        wmNews.setSubmitedTime(new Date());
        wmNews.setUserId(WmThreadLocalUtil.getUser().getId());
        //1.判断是否是包含id
        if (wmNews.getId() != null) {
            //修改业务
            //删除中间表
            wmNewsMaterialMapper.delete(Wrappers.<WmNewsMaterial>lambdaQuery()
                    .eq(WmNewsMaterial::getNewsId, wmNews.getId()));
            //修改文章表
            updateById(wmNews);
        } else {
            //新增
            save(wmNews);
        }
    }


    /*
     * @description: 查询文章详情
     * @author: 椎名真白
     * @date: 2022-06-14 21:34
     * @param: id
     * @return: com.heima.model.common.dtos.ResponseResult
     **/
    @Override
    public ResponseResult getOne(Integer id) {
        QueryWrapper<WmNews> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        WmNews news = this.getOne(queryWrapper);
        ResponseResult responseResult = new ResponseResult();
        responseResult.setCode(200);
        responseResult.setErrorMessage("操作成功");
        responseResult.setData(news);
        return responseResult;
    }

    @Override
    public ResponseResult MyremoveById(Integer id) {
        if (id == null) {
            return ResponseResult.errorResult(501, "文章id不可缺少");
        }
        QueryWrapper<WmNews> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("id",id);
        WmNews news = this.getOne(queryWrapper);
        if (news==null){
            return  ResponseResult.errorResult(1002,"文章不存在");
        }
        QueryWrapper<WmNewsMaterial> queryWrapper1=new QueryWrapper<>();
        queryWrapper1.eq("news_id",id);
        List<WmNewsMaterial> wmNewsMaterials = wmNewsMaterialMapper.selectList(queryWrapper1);
        if(wmNewsMaterials!=null && wmNewsMaterials.size()>0){
            return ResponseResult.errorResult(501,"文章已发布 不可删除");
        }
        //进行删除 将文章表和和中间表都进行删除
        this.removeById(id);
        wmNewsMaterialMapper.delete(queryWrapper1);
        return ResponseResult.okResult(200,"操作成功");
    }

    @Override
    public ResponseResult downOrUp(WmNewsDto wmNewsDto) {
        Integer id = wmNewsDto.getId();
        if (id == null) {
            return ResponseResult.errorResult(501, "文章id不可缺少");
        }
        QueryWrapper<WmNews> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("id",id);
        WmNews news = this.getOne(queryWrapper);
        if (news==null){
            return  ResponseResult.errorResult(1002,"文章不存在");
        }
        if (news.getStatus()!=9) {
            return ResponseResult.errorResult(501,"当前文章变速发布状态，不可进行上下架");
        }
        //进行文章的上下架
        news.setStatus(wmNewsDto.getEnable());
        this.updateById(news);
        return ResponseResult.okResult(200,"操作成功");
    }
}